#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL_net.h>

#include "messages.h"
#include "tankdata.h"

#define GET_BYTE(buffer, index) (*(((unsigned char*) (buffer)) + index))
#define GET_WORD(buffer, index) (*(unsigned short*)(((unsigned char*) (buffer)) + index))
//#define GET_BIT(byte, bit) (((byte) & (1 << (bit))) >> (bit))

int main(int argc, char **argv)
{
	UDPsocket sd;
	IPaddress srvadd;
	UDPpacket *p;
	int quit;
	int i;
	SDLNet_SocketSet set;
	TankPosition tankPos[30];
 
	/* Check for parameters */
	if (argc < 3)
	{
		fprintf(stderr, "Usage: %s host port\n", argv[0]);
		exit(EXIT_FAILURE);
	}
 
	/* Initialize SDL_net */
	if (SDLNet_Init() < 0)
	{
		fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}
 
	/* Open a socket on random port */
	if (!(sd = SDLNet_UDP_Open(0)))
	{
		fprintf(stderr, "SDLNet_UDP_Open: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}
 
	/* Resolve server name  */
	if (SDLNet_ResolveHost(&srvadd, argv[1], atoi(argv[2])) == -1)
	{
		fprintf(stderr, "SDLNet_ResolveHost(%s %d): %s\n", argv[1], atoi(argv[2]), SDLNet_GetError());
		exit(EXIT_FAILURE);
	}
 
	/* Allocate memory for the packet */
	if (!(p = SDLNet_AllocPacket(512)))
	{
		fprintf(stderr, "SDLNet_AllocPacket: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}

	// Create a socket set to handle 1 socket
	set = SDLNet_AllocSocketSet(1);
	if(!set) {
		fprintf(stderr, "SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}

	// add server socket to set
	numused = SDLNet_UDP_AddSocket(set, sd);
	if (numused == -1) {
		fprintf(stderr, "SDLNet_AddSocket: %s\n", SDLNet_GetError());
		exit (EXIT_FAILURE);
	}
	
	/* Main loop */
	quit = 0;
	while (!quit)
	{
		// send request to server
		*(int*)p->data = MessageId_MoveForward;
		p->len = sizeof(int);
 		p->address.host = srvadd.host;	/* Set the destination host */
		p->address.port = srvadd.port;	/* And destination port */
 		SDLNet_UDP_Send(sd, -1, p); /* This sets the p->channel */

		// receive update from server
		numready = SDLNet_CheckSockets(set, 30);
		if (numready == -1) {
			fprintf(stderr, "SDLNet_CheckSockets: %s\n", SDLNet_GetError());
			exit (EXIT_FAILURE);
		} else if (numready) {
			numpkts = SDLNet_UDP_Recv (udpsock, p);
			if (numpkts) {
				// process the packet
				ReadBuffer buf(p->data);
				// message id
				int msgId = buf.readByte();
				// tank count
				int tankCount = buf.readByte();
				for (i = 0; i < tankCount; i++)
				{
				  // tank index and state
				  unsigned char b = buf.readByte();
				  int tankIndex = (b & 0x7f);
				  tanksPos[tankIndex].state = (b & 0x80);
				  // tanks speed
				  tanksPos[tankIndex].speed = buf.readByte();
				  // tank coords (hull)
				  tanksPos[tankIndex].hullCenter.x = buf.readWord();
				  tanksPos[tankIndex].hullCenter.y = buf.readWord();
				  // tank turret
				}
			}
		}
		
		// draw frame
		// ...

		i++;
		if (i == 1000)
		{
			quit = 1;
		}
	}
 
	SDLNet_FreeSocketSet(set);
	SDLNet_FreePacket(p);
	SDLNet_Quit();
 
	return EXIT_SUCCESS;
}

